﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using Croxweb.Leuphana.Models;
using Croxweb.Leuphana.Services.MyStudyService;


namespace Croxweb.Leuphana.ViewModels
{
    public class ScheduleViewModel : ViewModelBase
    {
        private readonly IMyStudyService service;

        private CollectionViewSource monViewSource = new CollectionViewSource();
        private CollectionViewSource tueViewSource = new CollectionViewSource();
        private CollectionViewSource wedViewSource = new CollectionViewSource();
        private CollectionViewSource thuViewSource = new CollectionViewSource();
        private CollectionViewSource friViewSource = new CollectionViewSource();

        private CollectionViewSource singleViewSource = new CollectionViewSource();

        private ObservableCollection<AppointmentViewModel> appointments;

        private Boolean isSynchronizing;
        private Boolean isDataLoaded;


        // Constructor.
        public ScheduleViewModel(IMyStudyService service)
        {
            this.service = service;
        }


        // Status properties.
        public Boolean IsSynchronizing
        {
            get { return isSynchronizing; }
            set
            {
                isSynchronizing = value;
                NotifyPropertyChanged("IsSynchronizing");
            }
        }
        public Boolean IsDataLoaded
        {
            get { return isDataLoaded; }
            private set
            {
                isDataLoaded = value;
                NotifyPropertyChanged("IsDataLoaded");
            }
        }


        // List properties.
        public ICollectionView AppointmentsMon { get { return monViewSource.View; } }
        public ICollectionView AppointmentsTue { get { return tueViewSource.View; } }
        public ICollectionView AppointmentsWed { get { return wedViewSource.View; } }
        public ICollectionView AppointmentsThu { get { return thuViewSource.View; } }
        public ICollectionView AppointmentsFri { get { return friViewSource.View; } }

        public ICollectionView AppointmentsSingle { get { return singleViewSource.View; } }


        // Activities.
        public void Refresh()
        {
            if (!isDataLoaded)
            {
                IsDataLoaded = true;

                refresh();
            }
        }

        public void SyncSchedule()
        {
            if (!isSynchronizing)
            {
                IsSynchronizing = true;

                service.SynchronizeSchedule((lectures) =>
                {
                    refresh();

                    IsSynchronizing = false;
                });
            }
        }

        
        // Data handling.
        private void refresh()
        {
            appointments = new ObservableCollection<AppointmentViewModel>();
            Appointment lastAppointment = null;

            service.GetAllAppointments().ToList().ForEach((appointment) =>
            {
                AppointmentViewModel viewModel = new AppointmentViewModel(appointment);

                if (appointment.Recurrence == RecurrenceType.None)
                {
                    if (lastAppointment != null)
                    {
                        if (lastAppointment.StartDate == appointment.StartDate)
                        {
                            viewModel.ShowDate = Visibility.Collapsed;

                            if (lastAppointment.StartTime == appointment.StartTime)
                            {
                                viewModel.ShowTime = Visibility.Collapsed;
                            }
                        }
                    }

                    lastAppointment = appointment;
                }

                appointments.Add(viewModel);
            });

            monViewSource = new CollectionViewSource() { Source = appointments };
            tueViewSource = new CollectionViewSource() { Source = appointments };
            wedViewSource = new CollectionViewSource() { Source = appointments };
            thuViewSource = new CollectionViewSource() { Source = appointments };
            friViewSource = new CollectionViewSource() { Source = appointments };

            singleViewSource = new CollectionViewSource() { Source = appointments };

            #region Filters and Sortings

            // Filter by day and recurrence.
            monViewSource.Filter += (o, e) =>
            {
                e.Accepted = e.Item != null &&
                ((AppointmentViewModel)e.Item).StartDate.DayOfWeek == DayOfWeek.Monday &&
                (
                    ((AppointmentViewModel)e.Item).Recurrence == RecurrenceType.Weekly ||
                    ((AppointmentViewModel)e.Item).Recurrence == RecurrenceType.Fortnightly
                );
            };
            tueViewSource.Filter += (o, e) =>
            {
                e.Accepted = e.Item != null &&
                ((AppointmentViewModel)e.Item).StartDate.DayOfWeek == DayOfWeek.Tuesday &&
                ((AppointmentViewModel)e.Item).Recurrence != RecurrenceType.None;
            };
            wedViewSource.Filter += (o, e) =>
            {
                e.Accepted = e.Item != null &&
                ((AppointmentViewModel)e.Item).StartDate.DayOfWeek == DayOfWeek.Wednesday &&
                ((AppointmentViewModel)e.Item).Recurrence != RecurrenceType.None;
            };
            thuViewSource.Filter += (o, e) =>
            {
                e.Accepted = e.Item != null &&
                ((AppointmentViewModel)e.Item).StartDate.DayOfWeek == DayOfWeek.Thursday &&
                ((AppointmentViewModel)e.Item).Recurrence != RecurrenceType.None;
            };
            friViewSource.Filter += (o, e) =>
            {
                e.Accepted = e.Item != null &&
                ((AppointmentViewModel)e.Item).StartDate.DayOfWeek == DayOfWeek.Friday &&
                ((AppointmentViewModel)e.Item).Recurrence != RecurrenceType.None;
            };
            singleViewSource.Filter += (o, e) =>
            {
                e.Accepted = e.Item != null &&
                ((AppointmentViewModel)e.Item).Recurrence == RecurrenceType.None;
            };

            // Sortings for weekly views.
            monViewSource.SortDescriptions.Add(new SortDescription("StartTime", ListSortDirection.Ascending));
            tueViewSource.SortDescriptions.Add(new SortDescription("StartTime", ListSortDirection.Ascending));
            wedViewSource.SortDescriptions.Add(new SortDescription("StartTime", ListSortDirection.Ascending));
            thuViewSource.SortDescriptions.Add(new SortDescription("StartTime", ListSortDirection.Ascending));
            friViewSource.SortDescriptions.Add(new SortDescription("StartTime", ListSortDirection.Ascending));

            // Reset current item.
            monViewSource.View.MoveCurrentToPosition(-1);
            tueViewSource.View.MoveCurrentToPosition(-1);
            wedViewSource.View.MoveCurrentToPosition(-1);
            thuViewSource.View.MoveCurrentToPosition(-1);
            friViewSource.View.MoveCurrentToPosition(-1);
            singleViewSource.View.MoveCurrentToPosition(-1);

            #endregion

            // Update all properties.
            NotifyPropertyChanged(String.Empty);
        }
    }
}